package cn.com.hbhgkj.web;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Constructor;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.ServletActionContext;

import cn.com.hbhgkj.common.Pagination;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.opensymphony.xwork2.util.ValueStack;

public class PagingInterceptor extends AbstractInterceptor{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -1323019262551276045L;
	private static final String MSG_FIELD = "message";
	private static final String SUCCESS_FIELD = "success";
	private static final Log LOG = LogFactory.getLog(PagingInterceptor.class);
	private String errorMsg;

	public String intercept(ActionInvocation invocation) throws Exception {
		ValueStack stack = invocation.getStack();
		//initializing the target action
		//initAction(stack);
		
		Class<?> actionClazz = invocation.getAction().getClass();
        Class<?> pagingClazz = Pagination.class;
      //find the instance name in target action of Pagination
        String pagingName =  findPagingName(pagingClazz,actionClazz);
        //populate the new instance of pagination to current action 
        populatePaginationToAction(pagingName , pagingClazz , actionClazz  , stack);
        return invocation.invoke();
	}
	
	
	private String findPagingName(Class<?> type,Class<?> fromClazz){
		PropertyDescriptor[] pds = PropertyUtils.getPropertyDescriptors(fromClazz);
		for(PropertyDescriptor pd : pds){
			if(pd.getPropertyType().equals(type))
				return pd.getName();
		}
		this.errorMsg = "No pagination defined in " +fromClazz + " or you can remove this intercetor from action configuration!";
		LOG.error(errorMsg);
		throw new RuntimeException(errorMsg);
	}
	private void populatePaginationToAction(String fieldName , Class<?> pagingClazz , Class<?> actionClazz, ValueStack stack) throws Exception{
		HttpServletRequest request = ServletActionContext.getRequest();
        String limit = request.getParameter("limit");
        String start = request.getParameter("start");
        String asc = request.getParameter("asc");
        String orderByField = request.getParameter("orderByField");
        /*BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()));
        String readerLine;
        while((readerLine=reader.readLine()) != null){
        	System.out.println(readerLine);
        }*/
        Constructor<Pagination> constructor = null;
        Pagination pagination = null;
        Class<?> [] constructorParams;
        Object[] params;
        
      //get default constructor which will set both start and limit to -1.
        if( !isCustomeredPaging(start,limit)){
        	/*constructorParams = new Class<?>[]{};
        	params = new Object[]{};*/
        	return;
        }else{
        	//build customer pagination with given start and limit 
        	constructorParams = new Class<?>[]{Integer.class,Integer.class};
        	params = new Object[]{new Integer(start),new Integer(limit)};
        }
        constructor = this.getConstructorByParams(constructorParams);
        pagination = this.newPagination(constructor,params);
        
        if(orderByField != null && !orderByField.equals(""))
        	pagination.setOrderByField(orderByField);
        if(asc != null)
        	pagination.setAsc(new Boolean(asc));
        
        //update the targetField in valueStack with ognl's help to populate these fields 
        stack.setValue(fieldName, pagination);
	}
	
	private boolean isCustomeredPaging(String start, String limit) {
		return start != null ? limit != null : false;
	}

	private Pagination newPagination(Constructor<Pagination> constructor,
			Object[] params) throws Exception{
		return constructor.newInstance(params);
	}

	private Constructor<Pagination> getConstructorByParams(
			Class<?>[] constructorParams) throws Exception{
		return Pagination.class.getConstructor(constructorParams);
	}

	
}
